package ru.p03.tvipuskeditor.client.tvipuskeditor;


import com.bfr.client.selection.Range;
import com.bfr.client.selection.RangeEndPoint;
import com.bfr.client.selection.Selection;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.IFrameElement;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Text;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RichTextArea.Formatter;
import com.google.gwt.user.client.ui.TextBoxBase;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.VerticalPanel;

// TODO extend any GWT Widget
public class TvipuskEditorWidget extends HorizontalPanel {

	public static final String CLASSNAME = "tvipuskeditor";


//	/** Set the CSS class name to allow styling. */
//	public static final String CLASSNAME = "v-tvipuskeditor";

	public static final String REQUEST_FILENAME = "client_request_filename";

	public static final String REQUEST_FILENAME_VAL = "client request filename";

	public static final String RETURN_FILENAME = "client_return_filename";

	public static final String RETURN_TEXT = "return_text";
	
	public static final String TEXT_DELIMETER = "[PLAIN_TEXT:]";
	
	//public static final String CLICK_EVENT_IDENTIFIER = "click";

//	/** The client side widget identifier */
//	protected String paintableId;
//	// /** Component identifier in UIDL communications. */
//	// protected String uidlId;
//	/** Reference to the server connection object. */
//	protected ApplicationConnection client;

	//private HorizontalPanel basePanel = null;
	private VerticalPanel verticalPanel = null;
	RichTextArea editorText;

	private Button zkdButton;

	private Button snhButton;
		
	private Button subBlockButton;
	
//	private Tree blockTree;

//	private final VMaskedTextField tfTimeS;

//	private final VMaskedTextField tfTimePo;

//	private final Label lFilename;

//	private final Hyperlink hfilenameLink;

//	private final Label lDuration;

//	private final String fileNameBlock = null;

//	private final TextArea tfTitleBlock;

//	private final Button btnAttachFile;
	
//	private final Button btnApplyChange;

	private Range m_lastRange;

	static final String ZKD_TEXT = "ЗКД";

	static final String SNH_TEXT = "СНХ";

	static final String SKL_TEXT = "СКЛ";

	private final static String patternSNH_SKL = "\\{(СНХ|СКЛ)[\n\\s]С='\\d\\d:\\d\\d:\\d\\d'[\n\\s]" +
			"По='\\d\\d:\\d\\d:\\d\\d'[\n\\s]" +
			"Файл='.*'[\n\\s]Длительность='.*'[\n\\s]Титр='.*'\\}"; 
	
	private final static String patternZKD ="\\{ЗКД\\}";
	
	private static RegExp regExpSNH_SKL = RegExp.compile(patternSNH_SKL);
	
	private static RegExp regExpZKD = RegExp.compile(patternZKD);

	//private Block rootBlock = null;

	private TagAttrsDialog tagAttrsDialog = null;

	//private Block prevSelectedBlock = null;

	private EditorTextScanner textScan = new EditorTextScanner();


//	@Override
//	public void onBrowserEvent(Event event) {
//		 GWT.log("onBrowserEvent", null);
//		 
//		  event.stopPropagation();
//		  event.cancelBubble(true);//This will stop the event from being propagated
//		  event.preventDefault();
//		  switch (DOM.eventGetType(event)) {
//		    case Event.ONMOUSEUP:
//		      if (DOM.eventGetButton(event) == Event.BUTTON_LEFT) {
//		        GWT.log("Event.BUTTON_LEFT", null);
//		       // listener.onClick(this, event);
//		      }
//		   
//		      if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
//		        GWT.log("Event.BUTTON_RIGHT", null);
//		       // listener.onRightClick(this, event);
//		      }
//		      break;
//		    case Event.ONDBLCLICK:  
//		      break;
//		 
//		    case Event.ONCONTEXTMENU:
//		      GWT.log("Event.ONCONTEXTMENU", null);
//		      break;
//		 
//		    default:
//		      break; // Do nothing
//		  }//end switch	}
//	}
	
	
	
	/**
	 * The constructor should first call super() to initialize the component and
	 * then handle any initialization relevant to Vaadin.
	 */
	public TvipuskEditorWidget(){
		// setElement(Document.get().createDivElement());
		// This method call of the Paintable interface sets the component
		// style name in DOM tree

		// setStyleName(CLASSNAME);
		// Tell GWT we are interested in receiving click events
		// sinkEvents(Event.ONCLICK);
		// Add a handler for the click events (this is similar to FocusWidget.addClickHandler())
		// addDomHandler(this, ClickEvent.getType());
		// sinkEvents(Event.ONMOUSEUP | Event.ONDBLCLICK | Event.ONCONTEXTMENU);
		
		setStyleName(CLASSNAME);
		//setStyleName("reindeer");
		
		
		editorText = new RichTextArea();
		
//		editorText = new RichTextArea(){
//
//			 @Override
//			  public void onBrowserEvent(Event event) { 
//
//			    switch (event.getTypeInt()) {
//			    	 
//			    	case Event.ONPASTE: 
//			    		System.out.println("Paste Detected"); 
//			    		Window.alert("Paste Works!!! Yippie!!!");
//			    		break;
//			    	default:super.onBrowserEvent(event);
//			    } 
//			  } 
//
//		};
//		editorText.sinkEvents(Event.ONPASTE);
		
//		{
//			@Override
//			public void onBrowserEvent(Event event) {
//
//				GWT.log("on panel click: eventTypeInt: " + event.getTypeInt());
//
//				if ( (event.getTypeInt() == Event.ONCONTEXTMENU) ||
//					 (event.getTypeInt() == Event.ONMOUSEDOWN) ||
//					 (event.getTypeInt() == Event.ONMOUSEUP) )
//				{
//					GWT.log("on panel click: eventTypeInt: " + event.getTypeInt());
//					event.stopPropagation();
//					event.preventDefault();
//				}
//
////					switch (event.getTypeInt()) {
////					case Event.ONMOUSEUP:
////					case Event.ONCONTEXTMENU:
//////						if (DOM.eventGetCurrentTarget(event) == getElement()) {
//////							elementClicked(event);
//////						}						
////						GWT.log("on panel click: eventdTypeInt: " + event.getTypeInt());
////						event.stopPropagation();
////						event.preventDefault();
//						
////						break;
////					}
//			}
//		};

		//editorText.sinkEvents(Event.ONCONTEXTMENU | Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONDBLCLICK);

//		editorText.sinkEvents( Event.ONCONTEXTMENU );

		//editorText.setWidth("500px");
		//editorText.setHeight("300px");
		//editorText.setHeight("300px");
		//editorText.setText("{" + SNH_TEXT + "1}");
		//editorText.setHTML(EMPTY_HTML);
		editorText.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
//				if (event.isControlKeyDown()){
//					onDoubleClickInEditor(event);
//				}else{
//					onClickInEditor(event);
//				}
				onClickInEditor(event);
				}
		});

		editorText.addKeyDownHandler(new KeyDownHandler() {

			@Override
			public void onKeyDown(KeyDownEvent event) {
				//okKeyPressInEditor(event);
				onKeyDownInEditor(event);
			}
		});
		
		

//		editorText.addMouseDownHandler(new MouseDownHandler() {
//			
//			@Override
//			public void onMouseDown(MouseDownEvent event) {
//				//onMouseDownInEditor(event);
//				
//			}
//		});

//		editorText.addDoubleClickHandler(new DoubleClickHandler() {
//			
//			@Override
//			public void onDoubleClick(DoubleClickEvent event) {
//				onDoubleClickInEditor(event);
//				
//			}
//		});
		
//		editorText.addKeyPressHandler(new KeyPressHandler(){
//			@Override
//			public void onKeyPress(KeyPressEvent event){
//				okKeyPressInEditor(event);
//			}
//		});

		zkdButton = new Button("Закадровый");

		zkdButton.addClickHandler(zkdClickHandler);

		snhButton = new Button("Синхронный");

		snhButton.addClickHandler(snhClickHandler);

		subBlockButton = new Button("Подблок");

		subBlockButton.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event){
				//insertSubBlock();
				//trying to put image
				Formatter formatter = editorText.getFormatter();
				formatter.insertImage("/image1.gif");
			}
		});

//		tfTimeS = new VMaskedTextField();
//		tfTimeS.setColumns(8);
//		tfTimeS.setMask("##:##:##");
//
//		tfTimePo = new VMaskedTextField();
//		tfTimePo.setColumns(8);
//		tfTimePo.setMask("##:##:##");
//		
//		lFilename = new Label();
//		lFilename.setText("Файл: ");
//		
//		hfilenameLink = new Hyperlink();
//		hfilenameLink.setWidth("100px");
//		//hfilenameLink.setText("ссылка на имя файла");
//		hfilenameLink.setText("");
//		hfilenameLink.addClickHandler(new ClickHandler() {
//
//			@Override
//			public void onClick(ClickEvent event){
//				onFileLinkClick();
//			}
//		});
//
//		lDuration = new Label();
//		lDuration.setText("Длительность: ");
//
//		tfTitleBlock = new TextArea();
//		tfTitleBlock.setTitle("Титры:");
//		tfTitleBlock.setWidth("180px");
//		tfTitleBlock.setHeight("50px");
//
//		//tfFileName = new TextBox();
//		btnAttachFile = new Button("Прикрепить файл");
//		btnAttachFile.addClickHandler(new ClickHandler() {
// 
//			@Override
//			public void onClick(ClickEvent event){
//				chooseFile();
//			}
//		});
//		
//		btnApplyChange = new Button("Применить");
//		btnApplyChange.addClickHandler(new ClickHandler() {
// 
//			@Override
//			public void onClick(ClickEvent event){
//				setSnhAttrs();
//			}
//		});
		
		
		
//		blockTree = new Tree();
//		
//		blockTree.setAnimationEnabled(true);
//
//		blockTree.ensureSelectedItemVisible();
//
//		ScrollPanel blockTreeWrapper = new ScrollPanel(blockTree);
//
//		blockTreeWrapper.setSize("200px", "260px");
//
//		// Wrap the static tree in a DecoratorPanel
//	    DecoratorPanel blockTreeDecorator = new DecoratorPanel();
//
//	    blockTreeDecorator.setWidget(blockTreeWrapper);
//
//		blockTree.addSelectionHandler(new SelectionHandler<TreeItem>(){
//			@Override
//			public void onSelection(SelectionEvent<TreeItem> event){
//				onChangeTreeItem(event);
//			}
//		});
//
//		blockTree.addFocusHandler(new FocusHandler() {
//			
//			@Override
//			public void onFocus(FocusEvent event) {
////				log.setText(log.getText() + "addFocusHandler\n");
////				tfTimePo.setEnabled(false);
//			}
//		});
//		
//		blockTree.addBlurHandler(new BlurHandler() {
//			
//			@Override
//			public void onBlur(BlurEvent event) {
////				log.setText(log.getText() + "addBlurHandler\n");
////				tfTimePo.setEnabled(false);
//			}
//		});

//		log = new TextArea();
//		log.setWidth("300px");
//		log.setHeight("300px");


		
		//	basePanel = new HorizontalPanel();
		
		
		
		

//		final VerticalPanel leftPanel = new VerticalPanel();
		
//		final VerticalPanel timeAttrPanel = new VerticalPanel();
//
//		timeAttrPanel.setSpacing(5);
//		
//		timeAttrPanel.add(createTextBox(tfTimeS,"&#160;C:&#160;"));		
//
//		timeAttrPanel.add(createTextBox(tfTimePo,"По:"));
//
//		timeAttrPanel.add(lFilename);
//
//		timeAttrPanel.add(hfilenameLink);
//		
//		timeAttrPanel.add(lDuration);
//		
//		//timeAttrPanel.add(createTextBox(tfTitleBlock,"Заголовок блока:"));
//		
//		timeAttrPanel.add(new HTML("Титры:"));
//		timeAttrPanel.add(tfTitleBlock);
//
//		timeAttrPanel.add(btnAttachFile);
//		timeAttrPanel.add(btnApplyChange);
//
//	    DecoratorPanel timeAttrDecorator = new DecoratorPanel();
//	    timeAttrDecorator.setWidth("210px");
//	    timeAttrDecorator.setWidget(timeAttrPanel);		
//
//		leftPanel.add(blockTreeDecorator);
//
//	    leftPanel.add(timeAttrDecorator);
//		
//		basePanel.add(leftPanel);

		verticalPanel = new VerticalPanel();

		final HorizontalPanel toolPanel = new HorizontalPanel();

		toolPanel.setSpacing(5);

		toolPanel.add(zkdButton);

		toolPanel.add(snhButton);
		
		toolPanel.add(subBlockButton);

		verticalPanel.add(toolPanel);

		//DecoratorPanel editorTextDecorator = new DecoratorPanel();
		//editorTextDecorator.setWidget(editorText);
		editorText.setWidth("1200px");  //потом убрать
		editorText.setHeight("700px");
		verticalPanel.add(editorText);
		
		//verticalPanel.add(editorTextDecorator);

		//verticalPanel.setWidth("100%");
		//verticalPanel.setWidth("" + editorText.getOffsetWidth() + "px");

//		basePanel.add(verticalPanel);
		add(verticalPanel);
		
		//basePanel.setWidth("500px");
	//	basePanel.setWidth("" + 200 + verticalPanel.getOffsetWidth() + "px");

	//	basePanel.setHeight("300px");

//		basePanel.add(log);
		//basePanel.setBorderWidth(1);
		//basePanel.setWidth("100%");
		tagAttrsDialog = new TagAttrsDialog(this);
		tagAttrsDialog.addCloseHandler(new CloseHandler<PopupPanel>(){

			@Override
			public void onClose(CloseEvent<PopupPanel> event) {
				if(!tagAttrsDialog.isCanceled)
					setSnhOrSklAttrs();
			}
		});
		//initWidget(basePanel);

		//buildTree();

		//editorText.setFocus(true);
	}

	private HorizontalPanel createTextBox(final TextBoxBase textBox, String caption){
	    HorizontalPanel hPanel = new HorizontalPanel();
	    hPanel.setSpacing(4);
	    hPanel.add(new HTML(caption));
	    hPanel.add(textBox);
	    return hPanel;
	}
//    /**
//     * Called whenever an update is received from the server 
//     */
//	public void updateFromUIDL(UIDL uidl, ApplicationConnection client){
//		// This call should be made first. 
//		// It handles sizes, captions, tooltips, etc. automatically.
//		if (client.updateComponent(this, uidl, true)){
//		    // If client.updateComponent returns true there has been no changes and we
//		    // do not need to update anything.
//			return;
//		}
//		// Save reference to server connection object to be able to send
//		// user interaction later
//		this.client = client;
//		// Save the client side identifier (paintable id) for the widget
//		paintableId = uidl.getId();
//
//		// Process attributes/variables from the server
//		// The attribute names are the same as we used in 
//		// paintContent on the server-side
//		// int clicks = uidl.getIntAttribute("clicks");
//		// String message = uidl.getStringAttribute("message");
//
//		String xmltext = uidl.getStringAttribute("xmltext");
//
//		if ((xmltext != null) && !"".equals(xmltext)){
//			Block block = BlockFactory.toBlock(xmltext);
//			xmltext = "";
//			String text = textScan.getFormattedTextFromBlock(block);
//			editorText.setHTML(text);
//			//editorText.setText(text);
//		//	buildTree();
////			editorText.setHTML(text);
////			buildTree();
////			text = "";
//		}
//		
//		String filename = uidl.getStringAttribute("filename");
//		String duration = uidl.getStringAttribute("duration");
//		
//		//log.setText(log.getText() + "Считали file attrs, filename: " + filename);
//		
//		if (  ((filename != null) && !"".equals(filename)) || 
//			((duration != null) && !"".equals(duration)) )
//		{
//			//lFilename.setText(filename);
//			//log.setText(log.getText() + "updateFromUIDL: Получили имя файла. filename:" + filename);
//			//log.setText(log.getText() + "updateFromUIDL: Получили продолжительность. duration:" + duration);
//			
////			if(prevSelectedBlock != null){
////				prevSelectedBlock.setFileName(filename);
////				prevSelectedBlock.setDuration(duration);
////				
////				hfilenameLink.setText(
////						prevSelectedBlock.getFileName().substring( 					
////								prevSelectedBlock.getFileName().lastIndexOf('\\') + 1,
////								prevSelectedBlock.getFileName().length())
////				);
////				lDuration.setText(duration);
////			}else{
////				//log.setText(log.getText() + "updateFromUIDL: не выбран элемент дерева ");
////			}
//			tagAttrsDialog.lDuration.setText(duration);
//			tagAttrsDialog.hfilenameLink.setText(
//							filename.substring( 					
//							filename.lastIndexOf('\\') + 1,
//							filename.length())
//			);
//			tagAttrsDialog.fullFileName = filename;
//	}
//		String saveRequest = uidl.getStringAttribute("saveRequest");
//		if("saveRequest".equals(saveRequest)){
//			//log.setText(log.getText() + "Поступил запрос на передачу текста.");
//			save();
//		}
//
//		String widthTextEditor = uidl.getStringAttribute("widthtexteditor");
//		if((widthTextEditor != null) && !"".equals(widthTextEditor)){
//			//log.setText(log.getText() + "устанавливаем ширину редактора: " + widthTextEditor);
//			//basePanel.setWidth(widthTextEditor);
//			//basePanel.setWidth("" + 300 + widthTextEditor);
//			editorText.setWidth(widthTextEditor);
//			//verticalPanel.setWidth("" + editorText.getOffsetWidth() + "px");
//		}
//		String heightTextEditor = uidl.getStringAttribute("heighttexteditor");
//		if((heightTextEditor != null) && !"".equals(heightTextEditor)){
//			//log.setText(log.getText() + "устанавливаем ширину редактора: " + widthTextEditor);
//			//basePanel.setHeight(heightTextEditor);
//			editorText.setHeight(heightTextEditor);
//		}
//
//		String enabled = uidl.getStringAttribute("enabled");
//		if((enabled != null) && !"".equals(enabled)){
//			setEnabled(enabled);
//		}
//		//getElement().setInnerHTML("After <b>"+clicks+"</b> mouse clicks:\n" + message);
//	}

	public void setXmlText(String xmlText) {
		GWT.log(" setXmlText are invoking ");
		if ((xmlText != null) && !"".equals(xmlText)) {
			Block block = BlockFactory.toBlock(xmlText);

			String text = textScan.getFormattedTextFromBlock(block);
			editorText.setHTML(text);
		}
	}

	private void setEnabled(String enabled) {
		
		if("true".equals(enabled)){
			editorText.setEnabled(true);
			zkdButton.setEnabled(true);
			snhButton.setEnabled(true);
			subBlockButton.setEnabled(true);			
			//buildTree
			//GWT.log("editor text set visible true");
		}
		if("false".equals(enabled)){
			editorText.setEnabled(false);
			zkdButton.setEnabled(false);
			snhButton.setEnabled(false);
			subBlockButton.setEnabled(false);
			//buildTree
		}
		   
	}
//	/**
//	 * Посылает переменные на сервер
//	 *   
//	 *   returnText - текст из редактора в XML формате
//	 *   returnFilename - имя файла
//	 *   
//	 * @param returnText
//	 * @param returnFilename
//	 */
//	int valCounter = 0;
//	private void sendVariablesToServer (String returnText,
//										String returnFilename,
//										String requestFilename
//										){
//
//		 // Updating the state to the server can not be done
//		 // before the server connection is known, i.e., before
//		 // updateFromUIDL() has been called.
//		 if (paintableId == null || client == null)
//		     return;
//		 // Communicate the user interaction parameters to server.
//		 // This call will initiate an AJAX request to the server.
//
//		 if ((returnText != null) && !returnText.equals("")){
//			 client.updateVariable(paintableId, RETURN_TEXT, returnText + ":" + valCounter++, true);
//		 }
//		 if ((returnFilename != null) && !returnFilename.equals("")){
//			 String val = returnFilename + ":" + valCounter++;
//			// log.setText(log.getText() + "Посылаем на сервер имя файла: " + val + "\n");
//			 client.updateVariable(paintableId, RETURN_FILENAME, val, true);
//		 }
//		 if ((requestFilename != null) && !requestFilename.equals("")){
//			 client.updateVariable(paintableId, REQUEST_FILENAME, REQUEST_FILENAME_VAL + valCounter++, true);
//		 }		 
//	}

//	/**
//	 * 
//	 * Заменяет значение атрибута в блоке по его id
//	 * @param htmlText
//	 * @param id
//	 * @param attrName
//	 * @param newValueAttr
//	 * @return
//	 */
//	private String insertAttrToHTML(String htmlText, String id, String attrName, String newAttrValue){
//
//		int indId = htmlText.indexOf("id=\""+ id);
//		log.setText(log.getText() + " indOfId: " + indId);
//
//		if(indId < 0){
//			log.setText(log.getText() + "Ошибка. не найден Атрибут id. выходим\n");
//			return null;
//		}
//		int startInd = htmlText.indexOf(attrName +"=\"", indId);
//		
//		if(startInd < 0){
//			log.setText(log.getText() + "Ошибка. не найден Атрибут " + attrName + ". выходим\n");
//			return null;
//		}
//		startInd += attrName.length() + 2;
//
//		int endInd = htmlText.indexOf("\"", startInd);
//
//		if(endInd < 0){
//			log.setText(log.getText() + "Ошибка. не найден конец Атрибута " + attrName + ". выходим\n");
//			return null;
//		}
//		log.setText(log.getText() + "атрибуты startInd=" + startInd + " endInd="+endInd + "\n");
//
//		StringBuffer sb = new StringBuffer(htmlText);
//		sb.replace(startInd, endInd, newAttrValue);
//		return sb.toString();
//	}
	/**
	 * 
	 * Обработка нажатий кнопки в Редакторе
	 * 
	 */
	private void onKeyDownInEditor(KeyDownEvent event){
//		log.setText(log.getText() + " Нажали: " + event.getNativeKeyCode() + " ctrl: " + event.isControlKeyDown() +
//				" alt: " + event.isAltKeyDown());
		
		//49 - 1
		//50 - 2
		//51 - 3
		
//		if ((event.getNativeKeyCode() == 49) && event.isControlKeyDown()) {  //Комбинация ctrl-1
//			insertNewBlock(ZKD_TEXT);
//			event.preventDefault();
//			return; //Выходим, т.к. в insertNewBlock вызывается buildTree 
//		}
//		if ((event.getNativeKeyCode() == 50) && event.isControlKeyDown()) {  //Комбинация ctrl-2
//			insertNewBlock(SNH_TEXT);
//			event.preventDefault();
//			return;
//		}
//		if ((event.getNativeKeyCode() == 51) && event.isControlKeyDown()) {  //Комбинация ctrl-3
//			insertNewBlock(SKL_TEXT);
//			event.preventDefault();
//			return;
//		}
		int keyCode = event.getNativeKeyCode();
		
		if ( (keyCode == KeyCodes.KEY_DOWN) ||  
			 (keyCode == KeyCodes.KEY_UP) ||
			 (keyCode == KeyCodes.KEY_LEFT) ||
			 (keyCode == KeyCodes.KEY_RIGHT) ||
			 (keyCode == KeyCodes.KEY_HOME) ||
			 (keyCode == KeyCodes.KEY_END) ||
			 (keyCode == KeyCodes.KEY_PAGEDOWN) ||
			 (keyCode == KeyCodes.KEY_PAGEUP) )
		{
			return;
		}else{
			
			boolean isKey_Delete = keyCode == KeyCodes.KEY_DELETE;
			boolean isKey_Backspace = keyCode == KeyCodes.KEY_BACKSPACE;

			if (isIntoTag1()){
				event.preventDefault();
				return;
			}
			
			if(isKey_Delete){
				if (isIntoTagKeyDelete()){
					event.preventDefault();
				}
				return;
			}
			
			if(isKey_Backspace){
				if (isIntoTagKeyBackspace()){
					event.preventDefault();
				}
				return;
			}
			
		}
	//	buildTree();
		//selectTreeItem();  

		//blockTree.setFocus(false);
		//editorText.setFocus(true);

//		IFrameElement iframe = IFrameElement.as(editorText.getElement());
//        Document document = iframe.getContentDocument();
//        document.setScrollTop(document.getScrollHeight());
	}
	protected void onMouseDownInEditor(MouseDownEvent event) {

		if(event.getNativeButton() == com.google.gwt.dom.client.NativeEvent.BUTTON_RIGHT){
			parseText(event, false);
			//event.stopPropagation();
			//event.preventDefault();
		}

	}
//	/** 
//	 * Если двойной клик сделан по тегу СНХ, то открываем диалоговое окно
//	 * Почему то Не вызывается, поэтому закоментил 
//	 * @param event
//	 */
//	protected void onDoubleClickInEditor(ClickEvent event){
//		Range range_tag = isIntoTag(false);
//		if (range_tag != null){
//			Block block = null;
//			
//			try {
//				block = textScan.parseTagAttrs(range_tag.getText());
//			} catch (Exception e) {
//				//e.printStackTrace();
//				Window.alert("Ошибка: " + e.getMessage());
//				return;
//			}		
//			
//			if ((block != null) && (block.getBlockAtrType().equals(SNH_TEXT))){
//
//				if(tagAttrsDialog == null){
//					tagAttrsDialog = new TagAttrsDialog();
//				}
//				tagAttrsDialog.setBlockFieldsFromBlock(block);
//
//				tagAttrsDialog.myShow();
//			}		
//		}
//	}
	
	private void onClickInEditor(ClickEvent event){
		
		if(event.getNativeButton() == com.google.gwt.dom.client.NativeEvent.BUTTON_RIGHT){
			event.preventDefault();
		}
		parseText(event, event.isControlKeyDown());
	}

	/**
	 * Опредяляем находится ли курсор внутри тега
	 * @return Range всего тега или null
	 */
	private Range isIntoTag(int keyCode){
	
		Range range = getSelection().getRange();
		if(range == null)
			return null;
			
		Range newRange = __isIntoTag (range, keyCode, false);
		if(newRange != null) 
			return newRange;

		if (! range.isCursor() ){	//Если range - выделенный текст, то проверяем правую границу
			newRange = __isIntoTag (range, keyCode, true);
		}
			
		return newRange;
	}
	
	private boolean findTag1(String concat_str){
		MatchResult mr = regExpSNH_SKL.exec(concat_str);
		if (mr != null) 
			return true;
		
		mr = regExpZKD.exec(concat_str);
		
		return (mr != null); 
	}
	
	/**
	 * Поиск с конца строки Открывающейся фигурной скобки 
	 * Условие: Закрывающаяся фигурная скобка не должна встречаться после открывающейся.
	 * @param concat_str
	 * @return 
	 *   -1  -найден символ "}" - признак окончания поиска с отрицательным результатом
	 * 	  0  -не найден символ "{". также на найден символ "}"
	 *    1  -найден символ "{"
	 */
	private int findStartBracket(String concat_str){
		int indStartBracket = concat_str.lastIndexOf("{");
		
		int indEndBracket = concat_str.lastIndexOf("}");
		
		if ((indStartBracket < 0) && (indEndBracket < 0)) 
			return 0;

		if (indStartBracket > indEndBracket)
			return 1;
		else
			return -1;
	}
	
	/**
	 * Поиск с начала строки Закрывающейся фигурной скобки 
	 * Условие: Открывающаяся фигурная скобка не должна встречаться перед закрывающейся.
	 * @param concat_str
	 * @return 
	 *   -1  -найден символ "{" - признак окончания поиска с отрицательным результатом
	 * 	  0  -не найден символ "}". также на найден символ "{"
	 *    1  -найден символ "}"
	 */
	private int findEndBracket(String concat_str){
		int indStartBracket = concat_str.indexOf("{");
		
		int indEndBracket = concat_str.indexOf("}");
		
		if ((indStartBracket < 0) && (indEndBracket < 0)) 
			return 0;

		if ((indStartBracket >= 0) && (indEndBracket < 0)) 
			return -1;
		
		if (indStartBracket >= indEndBracket)
			return -1;
		else
			return 1;
	}
	
	
	/**
	 * Поиск тегов. Ищет в обратном направлении - от курсора к началу документа
	 * Условия выхода с отрицательным результатом:
	 *   - нашли символ закрытия тега "}"
	 *   - нашли Элемент (элемент - не текстовый узел) у которого среди дочерных
	 *     элементов не найден текстовый элемент    
	 * @param isKey_Backspace 
	 * @param isKey_Delete 
	 * @return  
	 */
	private boolean isIntoTag1() {
		
		Range range = getSelection().getRange();
	
		String leftPartStr = range.getCursor().getString(false);

		leftPartStr = moveBack(range.getCursor().getTextNode(), leftPartStr, true);
		boolean res = leftPartStr != null;
		GWT.log("concat_str = " + leftPartStr);
		
		if (!res)
			return false;

		String rightPartStr = range.getCursor().getString(true);
		rightPartStr = moveForward(range.getCursor().getTextNode(), rightPartStr, true);
		res = rightPartStr != null;
		GWT.log("concat_str = " + rightPartStr);

		if (!res)
			return false;
		
		String concat_str = leftPartStr + rightPartStr; 
		res = findTag1(concat_str);
		
		return res; 
	}

	private boolean isIntoTagKeyDelete() {
		Range range = getSelection().getRange();

		String rightPartStr = range.getCursor().getString(true);
				
		if((rightPartStr !=null) && (!"".equals(rightPartStr)))
			if (!rightPartStr.startsWith("{"))
				return false;
		   
		Text textNode = range.getCursor().getTextNode();
		
		//range.getCursor().isSpace(check)
		if((rightPartStr == null) || ("".equals(rightPartStr))){
			//int offset = range.getCursor().getOffset();
			//rightPartStr = textNode.getData();
			//range.getCursor().minimizeBoundaryTextNodes(true);
			
			textNode = isNextStartBracketNode(textNode);
			if(textNode==null)
				return false;
			rightPartStr = textNode.getData();
		}
		
		rightPartStr = rightPartStr.substring(1);
		
		String leftPartStr = "{";

		rightPartStr = moveForward(textNode, rightPartStr, true);
		boolean res = rightPartStr != null;
		GWT.log("concat_str = " + rightPartStr);

		if (!res)
			return false;

		String concat_str = leftPartStr + rightPartStr; 
		res = findTag1(concat_str);
		
		return res; 
	}
	
	private boolean isIntoTagKeyBackspace(){
		Range range = getSelection().getRange();

		String leftPartStr = range.getCursor().getString(false);
				
		if((leftPartStr !=null) && (!"".equals(leftPartStr)))
			if (!leftPartStr.endsWith("}"))
				return false;
		   
		Text textNode = range.getCursor().getTextNode();
		
		if((leftPartStr == null) || ("".equals(leftPartStr))){
			textNode = isPrevEndBracketNode(textNode);
			if(textNode==null)
				return false;
			leftPartStr = textNode.getData();
		}
		
		leftPartStr = leftPartStr.substring(0,leftPartStr.length() - 1);
		
		leftPartStr = moveBack(textNode, leftPartStr, true);
		boolean res = leftPartStr != null;
		GWT.log("concat_str = " + leftPartStr);

		if (!res)
			return false;

		String rightPartStr = "}";
		
		String concat_str = leftPartStr + rightPartStr; 
		res = findTag1(concat_str);
		
		return res; 
	}
	/**
	 * Определяет, что следующий текстовый элемент начинается с "{"
	 * @return
	 */
	private Text isNextStartBracketNode(Text textNode){		
		if (textNode==null)
			return null;
		//сначала проверка текущего тега 
		Text textCurrNode = isNextStartBracketNode1(textNode);
		if(textCurrNode!=null){
			return textCurrNode;
		}
		//Ищем следующий элемент, понимаем что у текста не может быть предков
		Node nextNode = textNode.getNextSibling();
		if (nextNode != null){
			return isNextStartBracketNode1(nextNode);
		}
		
		Node parentNode = textNode.getParentNode();
		
		while(parentNode != null){
			Node nextParentNode = parentNode.getNextSibling();
			if(nextParentNode != null){
				return isNextStartBracketNode1(nextParentNode);
			}
			parentNode = parentNode.getParentNode();
		}
		return null;
	}
		
	/**
	 * Определяет, что следующий текстовый элемент начинается с "{"
	 * @return
	 */
	private Text isNextStartBracketNode1(Node node){
		if (node==null)
			return null;
		//Ищем следующий элемент вниз по предкам и вправо
		
		if (node.getNodeType() == Node.ELEMENT_NODE){
			//проверка, что это за нода и возвращение
			String valueNode = node.getNodeName();
			if ("div".equalsIgnoreCase(valueNode)) //если Div и ..., то выходим (т.к. с Div происходит 
				return null;			 //корректное удаление, 
										 //span и т.д - обрабатываем	
			//движемся от предков
			if (node.hasChildNodes()){
				Node firstChild = node.getFirstChild();
				return isNextStartBracketNode1(firstChild);
			}
			return null;
		}else{
			if (node.getNodeType() == Node.TEXT_NODE){
				Text textNode = (Text)node;
				String text_str = textNode.getData();
				if(text_str.startsWith("{"))
					return textNode;
				else
					return null;
			}
		}
		return null;
	}
	
	/**
	 * Определяет, что предыдущий текстовый элемент начинается с "}"
	 * @return
	 */
	private Text isPrevEndBracketNode(Text textNode){		
		if (textNode==null)
			return null;
		//сначала проверка текущего тега 
		Text textCurrNode = isPrevEndBracketNode1(textNode);
		if(textCurrNode!=null){
			return textCurrNode;
		}
		//Ищем предыдущий элемент, понимаем что у текста не может быть предков
		Node prevNode = textNode.getNextSibling();
		if (prevNode != null){
			return isPrevEndBracketNode1(prevNode);
		}
		
		Node parentNode = textNode.getParentNode();
		
		while(parentNode != null){
			Node prevParentNode = parentNode.getPreviousSibling();
			if(prevParentNode != null){
				return isPrevEndBracketNode1(prevParentNode);
			}
			parentNode = parentNode.getParentNode();
		}
		return null;
	}	
	/**
	 * Определяет, что следующий текстовый элемент начинается с "{"
	 * @return
	 */
	private Text isPrevEndBracketNode1(Node node){
		if (node==null)
			return null;
		//Ищем следующий элемент вниз по предкам и вправо
		
		if (node.getNodeType() == Node.ELEMENT_NODE){
			//проверка, что это за нода и возвращение
			String valueNode = node.getNodeName();
			if ("div".equalsIgnoreCase(valueNode)) //если Div и ..., то выходим (т.к. с Div происходит 
				return null;			 //корректное удаление, 
										 //span и т.д - обрабатываем	
			//движемся от предков
			if (node.hasChildNodes()){
				Node lastChild = node.getLastChild();
				return isPrevEndBracketNode1(lastChild);
			}
			return null;
		}else{
			if (node.getNodeType() == Node.TEXT_NODE){
				Text textNode = (Text)node;
				String text_str = textNode.getData();
				if(text_str.endsWith("}"))
					return textNode;
				else
					return null;
			}
		}
		return null;
	}
		
	
	//рекурсивный поиск текста
	private String moveBack(Node node, String concat_str, boolean isFirstLevel){
		if (node == null){
			return null;
		}
		if (node.getNodeType() == Node.ELEMENT_NODE){
			//проверка, что это за нода и возвращение
			
			//движемся от предков
			if (node.hasChildNodes()){
				Node lastChild = node.getLastChild();
				return moveBack(lastChild, concat_str, false);
			}
			return null;
		}else{
			if (node.getNodeType() == Node.TEXT_NODE){
				Text textNode = (Text)node;
				
				if(!isFirstLevel){
					concat_str = textNode.getData() + concat_str;
				}
				
				GWT.log("concat_str = " + concat_str);
				
				int findStartBracketCode = findStartBracket(concat_str);
				
				if (findStartBracketCode == -1) //Найдена закр. скобка
					return null;
				if(findStartBracketCode == 1){//Нашли откр. скобку, проверка на тег
					//сначала строку отсекаем
					int indStartBracket = concat_str.lastIndexOf("{");
					concat_str = concat_str.substring(indStartBracket, concat_str.length());
					return concat_str;
				}
				//не нашли движемся дальше к началу текста
				
				//движемся от предков
				if (textNode.hasChildNodes()){
					Node lastChild = textNode.getLastChild();
					return moveBack(lastChild, concat_str, false);
				}
				
				Node prevNode = textNode.getPreviousSibling();
				if (prevNode != null){
					return moveBack(prevNode, concat_str, false);
				}
				
				Node parentNode = textNode.getParentNode();
				
				while(parentNode != null){
					Node prevParentNode = parentNode.getPreviousSibling();
					if(prevParentNode != null){
						return moveBack(prevParentNode, concat_str, false);
					}
					parentNode = parentNode.getParentNode();
				}
				return null;
				
			}else{
				GWT.log("Unknown node type");
				return null;
			}
		}
	}
	
	
	//рекурсивный поиск текста
	private String moveForward(Node node, String concat_str, boolean isFirstLevel){
		if (node == null){
			return null;
		}
		if (node.getNodeType() == Node.ELEMENT_NODE){
			//проверка, что это за нода и возвращение
			
			//движемся от предков
			if (node.hasChildNodes()){
				Node firstChild = node.getFirstChild();
				return moveForward(firstChild, concat_str, false);
			}
			return null;
		}else{
			if (node.getNodeType() == Node.TEXT_NODE){
				Text textNode = (Text)node;
				
				if(!isFirstLevel){
					concat_str = concat_str + textNode.getData();
				}
				
				GWT.log("concat_str = " + concat_str);
				
				int findEndBracketCode = findEndBracket(concat_str);
				
				if (findEndBracketCode == -1) //Найдена откр. скобка
					return null;
				if(findEndBracketCode == 1){//Нашли закр. скобку, проверка на тег
					//сначала строку отсекаем
					int indEndBracket = concat_str.indexOf("}");
					concat_str = concat_str.substring(0,indEndBracket+1);
					return concat_str;
				}
				
				//не нашли, движемся дальше к концу текста
				
				//движемся от предков
				if (textNode.hasChildNodes()){
					Node firstChild = textNode.getFirstChild();
					return moveForward(firstChild, concat_str, false);
				}
				
				Node nextNode = textNode.getNextSibling();
				if (nextNode != null){
					return moveForward(nextNode, concat_str, false);
				}
				
				Node parentNode = textNode.getParentNode();
				
				while(parentNode != null){
					Node nextParentNode = parentNode.getNextSibling();
					if(nextParentNode != null){
						return moveForward(nextParentNode, concat_str, false);
					}
					parentNode = parentNode.getParentNode();
				}
				return null;
				
			}else{
				GWT.log("Unknown node type");
				return null;
			}
		}
	}
			
	
	private Node getTerminalSibling(Node nextSibling) {
		//GWT.log("nextSibling: " + nextSibling + " type node: " + nextSibling.getNodeType());
		//GWT.log("nextSibling has Parent" + nextSibling.hasChildNodes());
		Node terminalNode = nextSibling;
		//Node terminalNode = nextSibling.getFirstChild();
		while (terminalNode.hasChildNodes()){
			terminalNode = terminalNode.getFirstChild(); 
		} 
		return terminalNode;
	}	
	
	
	private Range __isIntoTag (Range range, int keyCode, boolean isStart){
		
		RangeEndPoint rep = null;
		if (isStart)
			rep = range.getStartPoint();
		else
			rep = range.getEndPoint();

		if(rep == null)
			return null;

		String strLeft =  rep.getString(false);
		String strRight =  rep.getString(true);
		int offsetCursor = rep.getOffset();

		String str = strLeft + strRight;
		
		int lenLeft = strLeft.length();
		boolean isKey_Delete = keyCode == KeyCodes.KEY_DELETE;
		boolean isKey_Backspace = keyCode == KeyCodes.KEY_BACKSPACE;
		if (isKey_Delete){
			if ((strLeft != null) && (offsetCursor == lenLeft)){
				if((strRight == null) || "".equals(strRight)){//Находимся с краю						
					//Берем следующий Range
					Text textElem = rep.getTextNode();

					Node nextSibling = textElem.getNextSibling();
					//Проверка что мы в дочернем элементе
					if (nextSibling == null){
						if (textElem.hasParentElement()){
							if (textElem.getParentElement() != null){
								nextSibling = textElem.getParentElement().getNextSibling();
							}
						}
					}

					Text nextNode = null;
					if (nextSibling!=null){
						GWT.log("nextSibling: " + nextSibling + " type node: " + nextSibling.getNodeType());
						GWT.log("nextSibling has Parent" + nextSibling.hasChildNodes());
						nextSibling = getTerminalSibling(nextSibling);
						if(nextSibling.getNodeType()==Node.TEXT_NODE){
//							if(nextSibling.hasChildNodes()){
//								nextNode = Range.getAdjacentTextElement(textElem, true);
//							}
							nextNode = (Text)nextSibling;
						}else{
							//nextNode = (Text)nextSibling;
							nextNode = null;
						}
					}else{
						GWT.log("nextSibling: " + nextSibling );
						
						//nextNode = Range.getAdjacentTextElement(textElem, true);
					}

					//GWT.log("textElem.hasChildNodes(): " + textElem.hasChildNodes());
					//if (nextNode == null){
//						Text textElemNext = Range.getAdjacentTextElement(textElem, true);
//						if (textElemNext != null){
//							nextNode = textElemNext;
//						}
					//}

				    

					//if ((nextNode != null) && (nextNode.getNodeType() == Node.TEXT_NODE)){
					if (nextNode != null){
						//textElem = (Text)nextNode;

						    String textNextElem = "";
						    //if (textElem != null){
							textNextElem = nextNode.getData();
							rep.setTextNode(nextNode,true);

							RangeEndPoint repStart = new RangeEndPoint(nextNode,true);
							RangeEndPoint repEnd = new RangeEndPoint(nextNode,true);

							//rep.setOffset(1);
							range = new Range(repStart,repEnd);
							//range.setStartPoint(rep);
							//range.setEndPoint(rep);
							offsetCursor = 0;
						//}
						//str = str + textNextElem;
						str = textNextElem;
					}
				}
			}
		}
		String tag_prefix_zkd = "{" + ZKD_TEXT;
		String tag_prefix_snh = "{" + SNH_TEXT;
		String tag_prefix_skl = "{" + SKL_TEXT;

		boolean intoTag = false;

		int end_tag_offset = -1;
		boolean isLoop = true;
		int lastStartTagOffset = -1;
		int start_tag_offset = -1;
		while (isLoop) {
			isLoop = false;
			start_tag_offset = str.indexOf(tag_prefix_zkd, lastStartTagOffset+1);
			if(start_tag_offset >= 0){
				isLoop = true; 
				lastStartTagOffset = start_tag_offset;				
				end_tag_offset = str.indexOf('}',start_tag_offset);
				
				if (isKey_Delete && (offsetCursor == start_tag_offset) )
					offsetCursor ++;			
				if ((isKey_Backspace) && (offsetCursor - end_tag_offset == 1) )
					offsetCursor --;
				
				if( (offsetCursor > start_tag_offset) && (offsetCursor <= end_tag_offset) ){
					intoTag = true;
					isLoop = false;
				}
			}
	
			if (!intoTag){				
				start_tag_offset = str.indexOf(tag_prefix_snh,lastStartTagOffset+1);				
				if(start_tag_offset >= 0){
					isLoop = true;
					lastStartTagOffset = start_tag_offset;
					end_tag_offset = str.indexOf('}', start_tag_offset);
					
					if (isKey_Delete && (offsetCursor == start_tag_offset) )
						offsetCursor ++;
					if ((isKey_Backspace) && (offsetCursor - end_tag_offset == 1) )
						offsetCursor --;
					
					end_tag_offset = str.indexOf('}', start_tag_offset);
					if( (offsetCursor > start_tag_offset) && (offsetCursor <= end_tag_offset) ){
						intoTag = true;
						isLoop = false;
					}
				}
			}
			if (!intoTag){
				start_tag_offset = str.indexOf(tag_prefix_skl,lastStartTagOffset+1);				
				if(start_tag_offset >= 0){
					isLoop = true;
					lastStartTagOffset = start_tag_offset;
					end_tag_offset = str.indexOf('}', start_tag_offset);
	
					if (isKey_Delete && (offsetCursor == start_tag_offset) )
						offsetCursor ++;				
					if ((isKey_Backspace) && (offsetCursor - end_tag_offset == 1) )
						offsetCursor --;
	
					if( (offsetCursor > start_tag_offset) && (offsetCursor <= end_tag_offset) ){
						intoTag = true;
						isLoop = false;
					}
				}
			}
		}
		
		if (intoTag){
			RangeEndPoint repStart = range.getStartPoint();
			repStart.setOffset(start_tag_offset);
	
			RangeEndPoint repEnd = range.getEndPoint();
			repEnd.setOffset(end_tag_offset + 1);

			range = new Range(repStart, repEnd);

			return range;
		}
		return null;
	}
	
	
	

	/**
	 * 
	 * @param event
	 * @param isShowDialog - флаг, когда true надо показать диалоговое окно свойств тега
	 */
	private void parseText(DomEvent event, boolean isShowDialog){
		boolean isDelOrBackspase = (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_DELETE)  ||
			(event.getNativeEvent().getKeyCode() == KeyCodes.KEY_BACKSPACE); 
		Range range_tag = isIntoTag(event.getNativeEvent().getKeyCode());
		if (range_tag != null){
			//GWT.log("Внутри тега редактирование запрещено. ");
			event.preventDefault();

			//парсим атрибуты тега и отображаем их на панели
			Block block = null;			
			try {
				String text = range_tag.getText();
				block = textScan.parseTagAttrs(text);
			} catch (Exception e) {
				//e.printStackTrace();
				Window.alert("Ошибка: " + e.getMessage());
				return;
			}		
		
			if ((block != null) && (BlockFactory.isAttrsBlock(block))){
				if (isShowDialog){

					tagAttrsDialog.setBlockFieldsFromBlock(block);

					tagAttrsDialog.myShow();
				}
			}
		}
	}

	
//	private boolean isSnhBlockBefore(){
//		
//		
//		Range range = getSelection().getRange();
//		if(range == null)
//			return false;
//
//		RangeEndPoint rep = range.getEndPoint();
//		if(rep == null)
//			return false;
//		
//		String strLeft =  rep.getString(false);
//		
//		while 
//		
//		int lenLeft = strLeft.length();
//		boolean isKey_Delete = keyCode == KeyCodes.KEY_DELETE;
//		boolean isKey_Backspace = keyCode == KeyCodes.KEY_BACKSPACE;
//		if (isKey_Delete){
//			if ((strLeft != null) && (offsetCursor == lenLeft)){
//				if((strRight == null) || "".equals(strRight)){//Находимся с краю						
//					//Берем следующий Range
//					Text textElem = rep.getTextNode();
//
//					Node nextSibling = textElem.getNextSibling();
//					
//					
//		
//		return false;
//	}
				
				
				
//	private void setEnableBlockControls(boolean enable){
//		tfTimeS.setEnabled(enable);		
//		tfTimePo.setEnabled(enable);
//		tfTitleBlock.setEnabled(enable);
//		btnAttachFile.setEnabled(enable);
//		btnApplyChange.setEnabled(enable);
//	}
	
//	/**
//	 * парсим атрибуты тега
//	 */
//	private Block parseTagAttrs(Range range_tag){
//		try{
//			Block block = new Block();
//			
//			String tag_text = range_tag.getText();
//			if ("".equals(tag_text))
//				throw new Exception("Тег пуст");
//			if (tag_text.length() < 5)
//				throw new Exception("Маленькая длина для тега");
//			
//			int ind_start = tag_text.indexOf('{');
//			if (ind_start < 0)
//				throw new Exception("Не найдена скобка : {");
//			String tag_type = tag_text.substring(ind_start+1, ind_start + 4);
//			
//			block.setBlockAtrType(tag_type);
//			if (!SNH_TEXT.equals(tag_type)){ //Тип тега не СНХ, выходим
//				 return block;
//			}
//			//Продолжаем разбор тега СНХ
//			ind_start = tag_text.indexOf("С='",ind_start);
//			if (ind_start < 0)
//				throw new Exception("Не найден текст: С='");
//			int ind_end = tag_text.indexOf("'",ind_start + 3);
//			if (ind_end < 0)
//				throw new Exception("Не найдена закрывающая кавычка");
//			String time_s = tag_text.substring(ind_start + 3, ind_end);
//			
//			
//			ind_start = tag_text.indexOf("По='", ind_end);
//			if (ind_start < 0)
//				throw new Exception("Не найден текст: По='");			
//			ind_end = tag_text.indexOf("'", ind_start + 4);
//			if (ind_end < 0)
//				throw new Exception("Не найдена закрывающая кавычка");
//			String time_po = tag_text.substring(ind_start + 4, ind_end);
//			
//			
//			ind_start = tag_text.indexOf("Файл='",ind_end);
//			if (ind_start < 0)
//				throw new Exception("Не найден текст: Файл='");
//			ind_end = tag_text.indexOf("'", ind_start + 6);
//			if (ind_end < 0)
//				throw new Exception("Не найдена закрывающая кавычка");
//			String file_name = tag_text.substring(ind_start + 6, ind_end);
//
//			
//			ind_start = tag_text.indexOf("Длительность='",ind_end);
//			if (ind_start < 0)
//				throw new Exception("Не найден текст: Длительность='");
//			ind_end = tag_text.indexOf("'", ind_start + 14);
//			if (ind_end < 0)
//				throw new Exception("Не найдена закрывающая кавычка");
//			String file_duration = tag_text.substring(ind_start + 14, ind_end);
//
//			ind_start = tag_text.indexOf("Титр='",ind_end);
//			if (ind_start < 0)
//				throw new Exception("Не найден текст: Титр='");
//			ind_end = tag_text.indexOf("'", ind_start + 6);
//			if (ind_end < 0)
//				throw new Exception("Не найдена закрывающая кавычка");
//			String tag_title = tag_text.substring(ind_start + 6, ind_end);
//
//			block.setBlockAtrTitle(tag_title);
//			block.setDuration(file_duration);
//			block.setFileName(file_name);
//			block.setPo(time_po);
//			block.setS(time_s);
//
//			return block;
//		}catch(Exception e){
//			String err = "Ошибка при разборе тега. Текст ошибки: " + e.getMessage(); 
//			GWT.log(err);
//			//tfTitleBlock.setText(err);
//			//setEnableBlockControls(false);
//			return null;
//		}
//	}
//	
	
	/**
	 * Перерисовывает дерево тегов, сканируя текст
	 */
	private void refreshTree(){
//		blockTree.removeItems();
//		String text = editorText.getText();
//		text = text.replaceAll("&nbsp;", "&#160;");
//		text = text.replaceAll("<br>", "<br/>");
//
//		textScan.first();
//		textScan.setText(text);
//
//		TreeItem item = null;
////		log.setText(log.getText() + "текст:" + text + "\n");
//		Block block = textScan.getNextBlock();
//		while (block != null){
//			String tag = block.getBlockAtrType();
//	//		log.setText(log.getText() + "нашли тэг:" + tag + " id:" + block.getId() + "\n");
//			if((tag.equals(ZKD_TEXT)) || (tag.equals(SNH_TEXT))){
//				item = new TreeItem(tag + " " + block.getId() );
//
//				item.setUserObject(block);
//				blockTree.addItem(item);
//				if (prevSelectedBlock == block){
//					blockTree.setSelectedItem(item, false);
//				}
//			}
//			if((tag.equals(SKL_TEXT) && (item != null))){
//				TreeItem child = new TreeItem(tag + " " + block.getId());
//				child.setUserObject(block);
//				item.addItem(child);
//				
//				if (prevSelectedBlock == block){
//					item.setState(true, false);
//					
//					blockTree.setSelectedItem(child, false);
//				}					
//			}
//			block = textScan.getNextBlock();
//		}
//		DeferredCommand.add(new Command() { public void execute(){
//			editorText.setFocus(true);
//		}});		
	}
	
//	private int getCursorPosInHtml(){
//		try{
//			editorText.setFocus(true);
//			log.setText(log.getText() + " Установили фокус");
//
//			Selection selection = getSelection();
//			if (selection == null){
//				return 0;
//			}
//			Range range = selection.getRange();
//			if (range == null){
//				return 0;
//			}
//
//			List<Text>textList = range.getSelectedTextElements();
//	//		//log.setText(log.getText() + " text list size: "+ textList.size());
//			Text textElem = textList.get(0);
//
//			String textData = textElem.getData();
//
//	//		log.setText(log.getText() + " text data: " + textData);			
//	//		range = new Range(new RangeEndPoint(textElem, true),
//	//				new RangeEndPoint(textElem, false));
//
//	//		log.setText(log.getText() + " htmlRangeText: " + htmlRangeText);
//
//	//		int indOfId = htmlRangeText.indexOf("id=\"");
//	//		log.setText(log.getText() + " indOfId: " + indOfId);
//
//	//		String oldBlockId = null;
//	//		if(indOfId > 0){
//	//			int endInd = htmlRangeText.indexOf("\"", indOfId);
//	//			oldBlockId = htmlRangeText.substring(indOfId, endInd);
//	//			log.setText(log.getText() + " oldBlockId: " + oldBlockId);
//	//		}
//	//		if(oldBlockId == null){
//	//			log.setText(log.getText() + " oldBlockId is null, return: ");
//	//			return;
//	//		}
//
//			String htmlText = editorText.getHTML();
//			int ind = htmlText.indexOf(textData);
//			//int ind = htmlText.indexOf(oldBlockId);
//
//			return ind;
//		}catch (Exception e){
//			log.setText(log.getText() + " Ошибка: " + e.getMessage() + "\n");
//			return 0;
//		}
//	}
//	/**
//	 * Ищет по блок по id
//	 */
//	private RangeEndPoint findTagById(String id_block){
//
//		Document doc = getDocument();
//
//		for ( Text res=Range.getAdjacentTextElement(doc, true); 
//			 (res != null); 
//			  res = Range.getAdjacentTextElement(res, true)){
//
//			String textData = res.getData();
//
//			//log.setText(log.getText() + "textData: " + textData + "\n");
//
//			textScan.setText(textData);
//			textScan.first();
//			Block block = textScan.getNextBlock();
//			while (block != null){
//				if( block.getId().equals(id_block) ){
//					//return new RangeEndPoint(res, textScan.getOffset()+5);  // Нашли тэг, и сдвигаем offset
//					return new RangeEndPoint(res, textScan.getOffset());  // Нашли тэг, и сдвигаем offset
//				}
//				block = textScan.getNextBlock();
//			}
//
////			offset = textData.indexOf("{");
//
////			while(offset >= 0){
////				//log.setText(log.getText() + "offset: " + offset);
////				String tag = textData.substring(offset, offset + 5);
////
////				if((tag.equals(ZKD_TAG)) || (tag.equals(SNH_TAG)) || tag.equals(SKL_TAG)){
////					if(temp_num == block_number){
////						return new RangeEndPoint(res, offset+5);  // Нашли тэг, и сдвигаем offset
////					}
////				}
////				offset = textData.indexOf("{", offset + 1);
////				temp_num++;
////			}
//		}
//		return null;
//	}
	

//	/**
//	 * Выделяет заданный блок по id в Редакторе
//	 * @param block_number
//	 */
//	private void selectBlock(Block block){
//		try{
//			//log.setText(log.getText() + "selectBlock: " + block.getId() + "\n");
//			if(block==null){
//				//log.setText(log.getText() + "Ошибка в методе selectBlock. аргумент block is null\n");
//				return;
//			}
//			// log.setText(log.getText() + " устанавливаем курсор: ");
//			// log.setText(log.getText() + "blockNum: " + block_number);
//			// com.google.gwt.xml.XML.
//			editorText.setFocus(true);
//
//			RangeEndPoint repEnd = findTagById(block.getId());
//			if (repEnd == null){
//			//	log.setText(log.getText() + "Ошибка, не нашли тэг. \n");
//				return;
//			}
//
////			String prevStr = repEnd.getString(false);
////			int prevStrOffset = 0;
////			if (prevStr != null){
////				prevStrOffset = prevStr.length(); 
////			}
//
//			RangeEndPoint repStart = new RangeEndPoint(repEnd.getTextNode(), 
//					textScan.getOffset() - textScan.getLengthTag() + 3 + block.getId().length());
//			//log.setText(log.getText() + "Получили repStart. \n");
//			repEnd.setOffset(repEnd.getOffset()-1);
//
//			Range rng = new Range(repStart, repEnd);
//
//			getSelection().setRange(rng);
//			//log.setText(log.getText() + "Выделили. \n");
//
//			Formatter formatter = editorText.getFormatter();
//			String attrs = BlockFactory.getAttributesLine(block);
//			if(!attrs.equals("")){
//				formatter.insertHTML(" " + attrs);
//			}
//			formatter.removeFormat();
//			//log.setText(log.getText() + "Поменяли текст. \n");
//
//			rng = getSelection().getRange();
//			repEnd = rng.getEndPoint();
//			repEnd.setOffset(repEnd.getOffset()+1);
//			rng.setCursor(repEnd);
//			getSelection().setRange(rng);
//
////			NativeEvent event = Document.get().createKeyPressEvent(false, false, false, false, 66);
////			DomEvent.fireNativeEvent(event, editorText);
//
//			//log.setText(log.getText() + "Устанавливаем курсор, проверяйте\n");
//			//editorText.setFocus(true);
//			/*
//			textScan.setText(textData);
//			textScan.first();
//			Block newBlock = textScan.getNextBlock();
//			RangeEndPoint rep2 = null;
//			
//			if (newBlock != null){
//				//log.setText(log.getText() + "Нашли block. id= " + newBlock.getId() +  "\n");
//				String prevStr = rep.getString(false);
//				int prevStrOffset = 0;
//				if (prevStr != null){
//					prevStrOffset = prevStr.length(); 
//				}
//				rep2 = new RangeEndPoint(rep.getTextNode(), 
//						prevStrOffset + textScan.getOffset() - textScan.getLengthTag() - 1);
//			}else{
//				//log.setText(log.getText() + "Не Нашли block. работаем дальше\n");
//				Text res = null;
//				Text prevRes = null;
//				for (res = Range.getAdjacentTextElement(rep.getTextNode(), true);
//				 (res != null)&&(newBlock==null);
//				  res = Range.getAdjacentTextElement(res, true)){
//					textData = res.getData();
//					//log.setText(log.getText() + "textData: " + textData + ". \n");
//					//log.setText(log.getText() + "textData: " + textData + "\n");
//
//					textScan.setText(textData);
//					textScan.first();
//					newBlock = textScan.getNextBlock();
//					//log.setText(log.getText() + "iteration. id= " + block.getId() +  "\n");
//
//					prevRes = res;
//				}
//				if(newBlock != null){
//					//log.setText(log.getText() + "Нашли block. id= " + newBlock.getId() +  "\n");
//					rep2 = new RangeEndPoint(prevRes, textScan.getOffset() - textScan.getLengthTag() - 1);
//				}else{
//					//log.setText(log.getText() + "Не Нашли блок, выделяем текущий до конца\n");
//					if (prevRes != null){
//						rep2 = new RangeEndPoint(prevRes, prevRes.getData().length() );
//					}else{
//						int endOffset = rep.getTextNode().getData().length();
//						rep2 = new RangeEndPoint(rep.getTextNode(), endOffset);
//					}
//				}
//			}
//			Range rng = new Range(rep, rep2);
//			getSelection().setRange(rng);
//			//log.setText(log.getText() + "Устанавливаем курсор, проверяйте\n");
//			editorText.setFocus(true);
//			*/
//		}catch (Exception e){
//		//	log.setText(log.getText() + "Возникла ошибка,текст: " + e.getMessage() + "\n");
//		}
//	}
//	
	/**  
	 * Событие на выбор элемента в дереве blockTree  
	 * @param event
	 */
	private void onChangeTreeItem(SelectionEvent<TreeItem> event){
	//	log.setText(log.getText() + "onChangeTreeItem\n");
		
//		if(prevSelectedBlock != null){//Записываем значения на экране в блок
//			prevSelectedBlock.setS(getTimeFromField(tfTimeS.getText()));
//			prevSelectedBlock.setPo(getTimeFromField(tfTimePo.getText()));
//			prevSelectedBlock.setBlockAtrTitle(tfTitleBlock.getText());
//		}
//
//		TreeItem selectedItem = blockTree.getSelectedItem();
//		Block selectedBlock = (Block)selectedItem.getUserObject();
//		if (selectedBlock != null){
//			//log.setText(log.getText() + "selectedBlock.getS(): " + selectedBlock.getS() + "\n");
//			tfTimeS.setText(selectedBlock.getS());
//			tfTimePo.setText(selectedBlock.getPo());
//			tfTitleBlock.setText(selectedBlock.getBlockAtrTitle());
//			//hfilenameLink.setText(selectedBlock.getFileName());
//			hfilenameLink.setText(
//					selectedBlock.getFileName().substring( 					
//							selectedBlock.getFileName().lastIndexOf('\\') + 1,
//							selectedBlock.getFileName().length())
//					);
//
//			lDuration.setText(selectedBlock.getDuration());
//		}else{
//	//		log.setText(log.getText() + "Ошибка selectedBlock is Null. \n");
//		}
//		selectBlock(selectedBlock);
//
//		prevSelectedBlock = selectedBlock;
//
//		DeferredCommand.add(new Command() { public void execute(){
//			editorText.setFocus(true);
//		}});
		
	}
	/**
	 *	Перестраивает blockTree 	
	 */
//	private void buildTree(){
////		log.setText(log.getText() + "Строим дерево\n");
//		String text = editorText.getHTML();
//
//		try{
//			blockTree.removeItems();
//			text = text.replaceAll("&nbsp;", "&#160;");
//			text = text.replaceAll("<br>", "<br/>");
//
//			textScan.first();
//			textScan.setText(text);
//
//			TreeItem item = null;
//	//		log.setText(log.getText() + "текст:" + text + "\n");
//			Block block = textScan.getNextBlock();
//			while (block != null){
//				String tag = block.getBlockAtrType();
//		//		log.setText(log.getText() + "нашли тэг:" + tag + " id:" + block.getId() + "\n");
//				if((tag.equals(ZKD_TEXT)) || (tag.equals(SNH_TEXT))){
//					item = new TreeItem(tag + " " + block.getId() );
//
//					item.setUserObject(block);
//					blockTree.addItem(item);
//					if (prevSelectedBlock == block){
//						blockTree.setSelectedItem(item, false);
//					}
//				}
//				if((tag.equals(SKL_TEXT) && (item != null))){
//					TreeItem child = new TreeItem(tag + " " + block.getId());
//					child.setUserObject(block);
//					item.addItem(child);
//					
//					if (prevSelectedBlock == block){
//						item.setState(true, false);
//						
//						blockTree.setSelectedItem(child, false);
//					}					
//				}
//				block = textScan.getNextBlock();
//			}
//			DeferredCommand.add(new Command() { public void execute(){
//				editorText.setFocus(true);
//			}});
//		}catch(Exception e){
//	//		log.setText(log.getText() + " Ошибка: " + e.getMessage() + "\n");
//		}
//	}
	/**
	 * По позиции курсора определяет текущий блок и 
	 * выделяет в blockTree соответсвующий item 
	 */
	private void selectTreeItem(){
//		try{
//		  //  log.setText(log.getText() + "selectTreeItem\n");
//			editorText.setFocus(true);
//			Selection selection = getSelection();
//			if (selection == null){
//				return;
//			}
//			Range range = selection.getRange();
//			if (range == null){
//				return;
//			}
//			RangeEndPoint rep = range.getCursor();
//
//			String textData = rep.getString(true);
//			textScan.setText(textData);
//			textScan.first();
//			Block block = textScan.getNextBlock();
//			if (block != null){
//			//	log.setText(log.getText() + "сразу нашли блок: " + block.getId() + "\n");
//			}
//			if(block == null){
//			//	log.setText(log.getText() + "ищем дальше\n");
//				for (Text res= Range.getAdjacentTextElement(rep.getTextNode(), true);
//				 (res != null)&&(block==null);
//				  res = Range.getAdjacentTextElement(res, true)){
//
//					textData = res.getData();
//				//	log.setText(log.getText() + "textData: " + textData + "\n");
//
//					textScan.setText(textData);
//					textScan.first();
//					block = textScan.getNextBlock();
//				//	log.setText(log.getText() + "iteration. id= " + block.getId() +  "\n");
//				}
//			}
//			if (block == null){
//			//	log.setText(log.getText() + "не нашли блок. ");
//			}
//			if (block != null){
//			//	log.setText(log.getText() + "нашли блок: " + block.getId() + "\n");
//				//Ищем в дереве
//				TreeItem prevItem = null;
//				for (int i=0; i<blockTree.getItemCount();i++){
//					TreeItem item = blockTree.getItem(i);
//					
//				//	log.setText(log.getText() + "iteration over tree. i= " + i +  "\n");
//					
//					Block itblock = (Block)item.getUserObject();
//					
//					if (itblock == block){
//						//blockTree.setSelectedItem(item,false);
//						if (prevItem != null){
//							blockTree.setSelectedItem(prevItem, false);
//						}else{
//							blockTree.setSelectedItem(item, false);
//						}
//						//log.setText(log.getText() + "Нашли блок который надо выделить: id= " + block.getId() +  "\n");
//						break;
//					}
//
//					prevItem = item;
//
//				//	log.setText(log.getText() + "child count:= " + item.getChildCount() +  "\n");
//					if(item.getChildCount()>0){
//						for (int j=0; j<item.getChildCount(); j++){
//							TreeItem child = item.getChild(j);
//							//log.setText(log.getText() + "iteration over child. j= " + j +  "\n");
//							
//							itblock = (Block)child.getUserObject();
//							
//							if(itblock == block){
//								//log.setText(log.getText() + "Нашли блок который надо выделить: id= " + block.getId() +  "\n");
//								//blockTree.setSelectedItem(item,false);
//								if (prevItem != null){
//									//item.setState(true, false);//Раскрываем родителя
//									blockTree.setSelectedItem(prevItem, false);
//								}else{
//									blockTree.setSelectedItem(item, false);
//								}
//								break;
//							}
//							prevItem = child;
//						}
//					}
//				}
//			}
//		}
//		catch(Exception e){
//			//log.setText(log.getText() + "Ошибка: " + e.getMessage() + "\n");
//		}
	}
	/**
	 * Вычисляет позицию курсора, Вставляет новый блок в editorText 
	 */
	private void insertNewBlock(String newTag){

//		Block newBlock = textScan.createBlock(null, newTag);
//
//		tfTimeS.setText(newBlock.getS());
//		tfTimePo.setText(newBlock.getPo());
//		tfTitleBlock.setText(newBlock.getBlockAtrTitle());
//		
		editorText.setFocus(true);		

		Formatter formatter = editorText.getFormatter();
		
		if ( newTag.equals(ZKD_TEXT) ){
			
			formatter.insertHTML(
"<br/><span><font color=\"blue\">{" + newTag + "}</font></span><span>&nbsp;</span>" );
		}else{
				tagAttrsDialog.newTag(newTag);
				
				tagAttrsDialog.myShow();
		}
		//prevSelectedBlock  = newBlock;		
		//buildTree();
		save();
	}

    private ClickHandler zkdClickHandler = new ClickHandler(){

		@Override  
		public void onClick(ClickEvent event){
			insertNewBlock(ZKD_TEXT);
		}
	};

    private ClickHandler snhClickHandler = new ClickHandler(){

		@Override
		public void onClick(ClickEvent event){		
			insertNewBlock(SNH_TEXT);
		}
	};

	private void insertSubBlock(){	
		//Проверка на то что вставляем с СКЛ блок
//		if (isSnhBlockBefore()){
//		
//			insertNewBlock(SKL_TEXT);
//		}
		insertNewBlock(SKL_TEXT);
	}

//	Выбрать файл, открывает окно диалога для выбора файла
//	private static native void clickOnInputFile(Element elem) /*-{
//       elem.click();
//   	}-*/;

	protected void chooseFile(){

		//sendVariablesToServer("", "", REQUEST_FILENAME);

	}
	
	/**
	 * Записывает значения полей в тег в редакторе
	 * В какой тег записывать определяем по позииции курсора
	 */
	protected void setSnhOrSklAttrs(){
		editorText.setFocus(true);

		Range range_tag = isIntoTag(-1);
		if (range_tag != null){	//Обновляем значения тега, для этого тег сначала выделяем
			getSelection().setRange(range_tag);
		}

		String attrs =  tagAttrsDialog.getTagAttrsFromFields();

		Formatter formatter = editorText.getFormatter();

		formatter.insertHTML("<div><br/><font color=\"blue\">" + attrs + "</font><br/><br/></div>");

		save();
	}

//	/**
//	 * Формирует пустую строку атрибтутов тега
//	 * @return
//	 */
//	private String getEmptyTagAttrs(){
//		StringBuilder sb = new StringBuilder();
//		sb.append(" С='00:00:00'");
//		sb.append(" По='00:00:00'");
//		sb.append(" Файл=''");
//		sb.append(" Длительность=''");
//		sb.append(" Титр=''");
//		return sb.toString();
//	}
		
	
	/**
	 * Посылает имя файла выбранного блока на сервер
	 */
    void onFileLinkClick(){
//		sendVariablesToServer("", tagAttrsDialog.fullFileName, "");
		
		
		
		
//		TreeItem selectedItem = blockTree.getSelectedItem();
//		if(selectedItem == null){
//	//		log.setText(log.getText() + "Элемент дерева не выбран, выходим. \n");
//			return;
//		}
//		Block selectedBlock = (Block)selectedItem.getUserObject();
//		if (selectedBlock == null){
//	//		log.setText(log.getText() + "Ошибка selectedBlock is Null. \n");
//			return;
//		}
//		//log.setText(log.getText() + "Посылаем на сервер имя файла: " +  selectedBlock.getFileName() + "\n");
//		sendVariablesToServer("", selectedBlock.getFileName(), "");
//		
//		//prevSelectedBlock = selectedBlock;
	}

	//Передаем текст на сервер
	private void save(){
		try{
			//Отправляем форматированный текст
			String text = editorText.getHTML();
			Block rootBlock = editorTextToBlock(text);
			String xmlString = BlockFactory.generateXml(rootBlock);

			//Отправялем "простой" текст
			String plain_text = editorText.getText();
			rootBlock = editorTextToBlock(plain_text);
			String xmlPlainText = BlockFactory.generateXml(rootBlock);

			String concat_text = xmlString + TEXT_DELIMETER + xmlPlainText;
		
			
//			sendVariablesToServer(concat_text, "", "");
			
			
			
		}catch (Exception e) {
			String err = "Ошибка при сохранении. Текст ошибки: " + e.getMessage();
			GWT.log(err);
			Window.alert(err);
		}
	}

	private Block editorTextToBlock(String text) throws Exception{

		textScan.first();
		textScan.setText(text);

		Block rootBlock = new Block();

		Block subBlock = textScan.getNextBlock();			
		// Текст до 1-го блока записываем в rootBlock
		if (subBlock != null){
			rootBlock.setText(text.substring(0,
					textScan.getOffset() - textScan.getLengthTag() - 1));				
		}else{
			rootBlock.setText(text);
		}

		Block prevBlock = null;
		while (subBlock != null) {
			String tag = subBlock.getBlockAtrType();

			if ((tag.equals(ZKD_TEXT)) || (tag.equals(SNH_TEXT))) {
				rootBlock.getBlocks().add(subBlock);
				prevBlock = subBlock;
			}
			if ((tag.equals(SKL_TEXT) && (prevBlock != null))) {
				prevBlock.getBlocks().add(subBlock);
			}
			int oldOffset = textScan.getOffset();
			Block newBlock = textScan.getNextBlock();

			if (newBlock != null) {
				newBlock.getBlocks().clear();

				String textData = text.substring(oldOffset, textScan.getOffset()
						- textScan.getLengthTag() - 1);
				subBlock.setText(textData);
			} else {
				String textData = text.substring(oldOffset, text.length());
				subBlock.setText(textData);
			}
			subBlock = newBlock;
		}
		return rootBlock;
	}
	
	private Text findNodeByNumber(int num){
		Text res;

		Document doc = getDocument();

		for (res = Range.getAdjacentTextElement(doc, true); (res != null)
				&& (num > 0); res = Range.getAdjacentTextElement(res, true)){
			num--;
		}

		return res;
	}
	/**
	 * This captures the selection when the mouse leaves the RTE, because in IE
	 * the selection indicating the cursor position is lost once another widget
	 * gains focus. Could be implemented for IE only.
	 */
	public void captureSelection(){
		try{
			m_lastRange = getSelection().getRange();
		}catch (Exception ex) {
			GWT.log("Error capturing selection for IE", ex);
		}
	}

	public Range getRange() {
		if (m_lastRange == null) {
			return getSelection().getRange();
		} else {
			return m_lastRange;
		}
	}
     
	public Selection getSelection() {
		Selection res = null;
		try {
			JavaScriptObject window = getWindow();
			res = Selection.getSelection(window);
		} catch (Exception ex) {
			GWT.log("Error getting the selection", ex);
			//log.setText(log.getText() + "Error getting the selection\n");
		}
		return res;
	}	
	
	public JavaScriptObject getWindow() {
		IFrameElement frame = editorText.getElement().cast();
		return getWindow(frame);
	}
	
    public static native JavaScriptObject getWindow(IFrameElement iFrame)
    /*-{
	var iFrameWin = iFrame.contentWindow || iFrame.contentDocument;

	if( !iFrameWin.document ) 
	{
	    iFrameWin = iFrameWin.getParentNode(); //FBJS version of parentNode
	}
	return iFrameWin;
    }-*/;
	
    public Document getDocument()
    {
    	return Selection.getDocument(getWindow());
    }



   
	
}